package middleware

import (
	"encoding/json"
	"net/http"
	"strings"
	"time"

	"gitee.com/wangshh_123/cross-pay-go/src/database"
	"gitee.com/wangshh_123/cross-pay-go/src/models"
	"gitee.com/wangshh_123/cross-pay-go/src/utils/common"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// AdminMiddleware 管理员权限中间件
func AdminMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从JWT中获取用户ID
		userID, exists := c.Get("user_id")
		if !exists {
			common.Error(c, http.StatusUnauthorized, "unauthorized", nil)
			c.Abort()
			return
		}

		// 检查用户是否有管理员权限
		var rolePermissions struct {
			Permissions json.RawMessage `gorm:"column:permissions"`
		}
		result := database.DB.Raw(`
			SELECT r.permissions 
			FROM roles r 
			JOIN user_roles ur ON ur.role_id = r.id 
			WHERE ur.user_id = ? AND r.status = 1
		`, userID).Scan(&rolePermissions)

		if result.Error != nil {
			common.Error(c, http.StatusInternalServerError, "error", result.Error)
			c.Abort()
			return
		}

		// 如果没有找到角色权限
		if result.RowsAffected == 0 {
			common.Error(c, http.StatusForbidden, "no_role", nil)
			c.Abort()
			return
		}

		// 如果权限为空，初始化为空对象
		if rolePermissions.Permissions == nil {
			rolePermissions.Permissions = []byte("{}")
		}

		// 尝试解析权限
		var permissions map[string]bool
		// 先尝试解析为数组
		var permissionsArray []string
		if err := json.Unmarshal(rolePermissions.Permissions, &permissionsArray); err == nil {
			permissions = make(map[string]bool)
			for _, perm := range permissionsArray {
				permissions[perm] = true
			}
		} else {
			// 如果数组解析失败，尝试解析为对象
			if err := json.Unmarshal(rolePermissions.Permissions, &permissions); err != nil {
				common.Error(c, http.StatusInternalServerError, "error", err)
				c.Abort()
				return
			}
		}

		// 检查是否有管理员权限
		if !permissions["admin:access"] {
			common.Error(c, http.StatusForbidden, "forbidden", nil)
			c.Abort()
			return
		}

		// 将权限信息存储到上下文中，以便后续使用
		c.Set("permissions", permissions)
		c.Next()
	}
}

func AdminAuth(db *gorm.DB) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从请求头获取 token
		authHeader := c.GetHeader("Authorization")
		if authHeader == "" {
			common.Error(c, http.StatusUnauthorized, "UNAUTHORIZED", nil)
			c.Abort()
			return
		}

		// 检查 token 格式
		parts := strings.Split(authHeader, " ")
		if len(parts) != 2 || parts[0] != "Bearer" {
			common.Error(c, http.StatusUnauthorized, "INVALID_TOKEN_FORMAT", nil)
			c.Abort()
			return
		}

		token := parts[1]

		// 验证 token
		var user models.User
		if err := db.Where("token = ? AND token_expires_at > ?", token, time.Now()).First(&user).Error; err != nil {
			common.Error(c, http.StatusUnauthorized, "INVALID_TOKEN", err)
			c.Abort()
			return
		}

		// 检查用户角色
		var userRole models.UserRole
		if err := db.Where("user_id = ?", user.ID).First(&userRole).Error; err != nil {
			common.Error(c, http.StatusForbidden, "NO_ROLE", err)
			c.Abort()
			return
		}

		// 检查角色权限
		var role models.Role
		if err := db.Where("id = ? AND status = 1", userRole.RoleID).First(&role).Error; err != nil {
			common.Error(c, http.StatusForbidden, "INVALID_ROLE", err)
			c.Abort()
			return
		}

		// 将用户信息存储到上下文中
		c.Set("user_id", user.ID)
		c.Set("role", role)

		c.Next()
	}
}

// PermissionMiddleware 权限校验中间件，可以传入指定的权限进行校验
func PermissionMiddleware(requiredPermission string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从JWT中获取用户ID
		userID, exists := c.Get("user_id")
		if !exists {
			common.Error(c, http.StatusUnauthorized, "unauthorized", nil)
			c.Abort()
			return
		}

		// 检查用户是否有指定权限
		var rolePermissions struct {
			Permissions json.RawMessage `gorm:"column:permissions"`
		}
		result := database.DB.Raw(`
			SELECT r.permissions 
			FROM roles r 
			JOIN user_roles ur ON ur.role_id = r.id 
			WHERE ur.user_id = ? AND r.status = 1
		`, userID).Scan(&rolePermissions)

		if result.Error != nil {
			common.Error(c, http.StatusInternalServerError, "error", result.Error)
			c.Abort()
			return
		}

		// 如果没有找到角色权限
		if result.RowsAffected == 0 {
			common.Error(c, http.StatusForbidden, "no_role", nil)
			c.Abort()
			return
		}

		// 如果权限为空，初始化为空对象
		if rolePermissions.Permissions == nil {
			rolePermissions.Permissions = []byte("{}")
		}

		// 尝试解析权限
		var permissions map[string]bool
		// 先尝试解析为数组
		var permissionsArray []string
		if err := json.Unmarshal(rolePermissions.Permissions, &permissionsArray); err == nil {
			permissions = make(map[string]bool)
			for _, perm := range permissionsArray {
				permissions[perm] = true
			}
		} else {
			// 如果数组解析失败，尝试解析为对象
			if err := json.Unmarshal(rolePermissions.Permissions, &permissions); err != nil {
				common.Error(c, http.StatusInternalServerError, "error", err)
				c.Abort()
				return
			}
		}

		// 检查是否有指定权限
		if !permissions[requiredPermission] {
			common.Error(c, http.StatusForbidden, "forbidden", nil)
			c.Abort()
			return
		}

		// 将权限信息存储到上下文中，以便后续使用
		c.Set("permissions", permissions)
		c.Next()
	}
}

// MultiPermissionMiddleware 多权限校验中间件，可以传入多个权限，只要有一个权限满足即可
func MultiPermissionMiddleware(requiredPermissions ...string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从JWT中获取用户ID
		userID, exists := c.Get("user_id")
		if !exists {
			common.Error(c, http.StatusUnauthorized, "unauthorized", nil)
			c.Abort()
			return
		}

		// 检查用户是否有指定权限
		var rolePermissions struct {
			Permissions json.RawMessage `gorm:"column:permissions"`
		}
		result := database.DB.Raw(`
			SELECT r.permissions 
			FROM roles r 
			JOIN user_roles ur ON ur.role_id = r.id 
			WHERE ur.user_id = ? AND r.status = 1
		`, userID).Scan(&rolePermissions)

		if result.Error != nil {
			common.Error(c, http.StatusInternalServerError, "error", result.Error)
			c.Abort()
			return
		}

		// 如果没有找到角色权限
		if result.RowsAffected == 0 {
			common.Error(c, http.StatusForbidden, "no_role", nil)
			c.Abort()
			return
		}

		// 如果权限为空，初始化为空对象
		if rolePermissions.Permissions == nil {
			rolePermissions.Permissions = []byte("{}")
		}

		// 尝试解析权限
		var permissions map[string]bool
		// 先尝试解析为数组
		var permissionsArray []string
		if err := json.Unmarshal(rolePermissions.Permissions, &permissionsArray); err == nil {
			permissions = make(map[string]bool)
			for _, perm := range permissionsArray {
				permissions[perm] = true
			}
		} else {
			// 如果数组解析失败，尝试解析为对象
			if err := json.Unmarshal(rolePermissions.Permissions, &permissions); err != nil {
				common.Error(c, http.StatusInternalServerError, "error", err)
				c.Abort()
				return
			}
		}

		// 检查是否有任一指定权限
		hasPermission := false
		for _, permission := range requiredPermissions {
			if permissions[permission] {
				hasPermission = true
				break
			}
		}

		if !hasPermission {
			common.Error(c, http.StatusForbidden, "forbidden", nil)
			c.Abort()
			return
		}

		// 将权限信息存储到上下文中，以便后续使用
		c.Set("permissions", permissions)
		c.Next()
	}
}

// AllPermissionMiddleware 全权限校验中间件，需要同时拥有所有指定的权限
func AllPermissionMiddleware(requiredPermissions ...string) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 从JWT中获取用户ID
		userID, exists := c.Get("user_id")
		if !exists {
			common.Error(c, http.StatusUnauthorized, "unauthorized", nil)
			c.Abort()
			return
		}

		// 检查用户是否有指定权限
		var rolePermissions struct {
			Permissions json.RawMessage `gorm:"column:permissions"`
		}
		result := database.DB.Raw(`
			SELECT r.permissions 
			FROM roles r 
			JOIN user_roles ur ON ur.role_id = r.id 
			WHERE ur.user_id = ? AND r.status = 1
		`, userID).Scan(&rolePermissions)

		if result.Error != nil {
			common.Error(c, http.StatusInternalServerError, "error", result.Error)
			c.Abort()
			return
		}

		// 如果没有找到角色权限
		if result.RowsAffected == 0 {
			common.Error(c, http.StatusForbidden, "no_role", nil)
			c.Abort()
			return
		}

		// 如果权限为空，初始化为空对象
		if rolePermissions.Permissions == nil {
			rolePermissions.Permissions = []byte("{}")
		}

		// 尝试解析权限
		var permissions map[string]bool
		// 先尝试解析为数组
		var permissionsArray []string
		if err := json.Unmarshal(rolePermissions.Permissions, &permissionsArray); err == nil {
			permissions = make(map[string]bool)
			for _, perm := range permissionsArray {
				permissions[perm] = true
			}
		} else {
			// 如果数组解析失败，尝试解析为对象
			if err := json.Unmarshal(rolePermissions.Permissions, &permissions); err != nil {
				common.Error(c, http.StatusInternalServerError, "error", err)
				c.Abort()
				return
			}
		}

		// 检查是否拥有所有指定权限
		for _, permission := range requiredPermissions {
			if !permissions[permission] {
				common.Error(c, http.StatusForbidden, "forbidden", nil)
				c.Abort()
				return
			}
		}

		// 将权限信息存储到上下文中，以便后续使用
		c.Set("permissions", permissions)
		c.Next()
	}
}
